<!DOCTYPE HTML>
<html lang="zh-Hans" class="light" dir="ltr">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>变量声明 - TypeScript 使用指南手册</title>


        <!-- Custom HTML head -->
        
        <meta name="description" content="TypeScript Handbook 中文翻译。">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff">

        <link rel="icon" href="../../favicon.svg">
        <link rel="shortcut icon" href="../../favicon.png">
        <link rel="stylesheet" href="../../css/variables.css">
        <link rel="stylesheet" href="../../css/general.css">
        <link rel="stylesheet" href="../../css/chrome.css">
        <link rel="stylesheet" href="../../css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="../../FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="../../fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../../highlight.css">
        <link rel="stylesheet" href="../../tomorrow-night.css">
        <link rel="stylesheet" href="../../ayu-highlight.css">

        <!-- Custom theme stylesheets -->

    </head>
    <body class="sidebar-visible no-js">
    <div id="body-container">
        <!-- Provide site root to javascript -->
        <script>
            var path_to_root = "../../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('light')
            html.classList.add(theme);
            var body = document.querySelector('body');
            body.classList.remove('no-js')
            body.classList.add('js');
        </script>

        <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            var body = document.querySelector('body');
            var sidebar = null;
            var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
            }
            sidebar_toggle.checked = sidebar === 'visible';
            body.classList.remove('sidebar-visible');
            body.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded affix "><a href="../../PREFACE.html">前言</a></li><li class="chapter-item expanded affix "><li class="part-title">快速上手</li><li class="chapter-item expanded "><a href="../../zh/tutorials/index.html"><strong aria-hidden="true">1.</strong> 快速上手</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/tutorials/typescript-in-5-minutes.html"><strong aria-hidden="true">1.1.</strong> 5 分钟了解 TypeScript</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/asp.net-core.html"><strong aria-hidden="true">1.2.</strong> ASP.NET Core</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/asp.net-4.html"><strong aria-hidden="true">1.3.</strong> ASP.NET 4</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/gulp.html"><strong aria-hidden="true">1.4.</strong> Gulp</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/knockout.html"><strong aria-hidden="true">1.5.</strong> Knockout.js</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/react-and-webpack.html"><strong aria-hidden="true">1.6.</strong> React 与 webpack</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/react.html"><strong aria-hidden="true">1.7.</strong> React</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/angular-2.html"><strong aria-hidden="true">1.8.</strong> Angular 2</a></li><li class="chapter-item expanded "><a href="../../zh/tutorials/migrating-from-javascript.html"><strong aria-hidden="true">1.9.</strong> 从 JavaScript 迁移到 TypeScript</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">手册</li><li class="chapter-item expanded "><a href="../../zh/handbook/index.html"><strong aria-hidden="true">2.</strong> 手册</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/handbook/basic-types.html"><strong aria-hidden="true">2.1.</strong> 基础类型</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/interfaces.html"><strong aria-hidden="true">2.2.</strong> 接口</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/functions.html"><strong aria-hidden="true">2.3.</strong> 函数</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/literal-types.html"><strong aria-hidden="true">2.4.</strong> 字面量类型</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/unions-and-intersections.html"><strong aria-hidden="true">2.5.</strong> 联合类型和交叉类型</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/classes.html"><strong aria-hidden="true">2.6.</strong> 类</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/enums.html"><strong aria-hidden="true">2.7.</strong> 枚举</a></li><li class="chapter-item expanded "><a href="../../zh/handbook/generics.html"><strong aria-hidden="true">2.8.</strong> 泛型</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">手册（进阶）</li><li class="chapter-item expanded "><a href="../../zh/reference/index.html"><strong aria-hidden="true">3.</strong> 手册（进阶）</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/reference/advanced-types.html"><strong aria-hidden="true">3.1.</strong> 高级类型</a></li><li class="chapter-item expanded "><a href="../../zh/reference/utility-types.html"><strong aria-hidden="true">3.2.</strong> 实用工具类型</a></li><li class="chapter-item expanded "><a href="../../zh/reference/decorators.html"><strong aria-hidden="true">3.3.</strong> Decorators</a></li><li class="chapter-item expanded "><a href="../../zh/reference/declaration-merging.html"><strong aria-hidden="true">3.4.</strong> 声明合并</a></li><li class="chapter-item expanded "><a href="../../zh/reference/iterators-and-generators.html"><strong aria-hidden="true">3.5.</strong> Iterators 和 Generators</a></li><li class="chapter-item expanded "><a href="../../zh/reference/jsx.html"><strong aria-hidden="true">3.6.</strong> JSX</a></li><li class="chapter-item expanded "><a href="../../zh/reference/mixins.html"><strong aria-hidden="true">3.7.</strong> 混入</a></li><li class="chapter-item expanded "><a href="../../zh/reference/modules.html"><strong aria-hidden="true">3.8.</strong> 模块</a></li><li class="chapter-item expanded "><a href="../../zh/reference/module-resolution.html"><strong aria-hidden="true">3.9.</strong> 模块解析</a></li><li class="chapter-item expanded "><a href="../../zh/reference/namespaces.html"><strong aria-hidden="true">3.10.</strong> 命名空间</a></li><li class="chapter-item expanded "><a href="../../zh/reference/namespaces-and-modules.html"><strong aria-hidden="true">3.11.</strong> 命名空间和模块</a></li><li class="chapter-item expanded "><a href="../../zh/reference/symbols.html"><strong aria-hidden="true">3.12.</strong> Symbols</a></li><li class="chapter-item expanded "><a href="../../zh/reference/triple-slash-directives.html"><strong aria-hidden="true">3.13.</strong> 三斜线指令</a></li><li class="chapter-item expanded "><a href="../../zh/reference/type-compatibility.html"><strong aria-hidden="true">3.14.</strong> 类型兼容性</a></li><li class="chapter-item expanded "><a href="../../zh/reference/type-inference.html"><strong aria-hidden="true">3.15.</strong> 类型推论</a></li><li class="chapter-item expanded "><a href="../../zh/reference/variable-declarations.html" class="active"><strong aria-hidden="true">3.16.</strong> 变量声明</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">手册（v2）</li><li class="chapter-item expanded "><a href="../../zh/handbook-v2/index.html"><strong aria-hidden="true">4.</strong> 手册（v2）</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/handbook-v2/type-manipulation/template-literal-types.html"><strong aria-hidden="true">4.1.</strong> 模版字面量类型</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">TypeScript 声明文件（.d.ts）</li><li class="chapter-item expanded "><a href="../../zh/declaration-files/index.html"><strong aria-hidden="true">5.</strong> 如何书写声明文件</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/declaration-files/introduction.html"><strong aria-hidden="true">5.1.</strong> 介绍</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/by-example.html"><strong aria-hidden="true">5.2.</strong> 举例</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/library-structures.html"><strong aria-hidden="true">5.3.</strong> 库结构</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/templates.html"><strong aria-hidden="true">5.4.</strong> 模板</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/do-s-and-don-ts.html"><strong aria-hidden="true">5.5.</strong> 最佳实践</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/deep-dive.html"><strong aria-hidden="true">5.6.</strong> 深入</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/publishing.html"><strong aria-hidden="true">5.7.</strong> 发布</a></li><li class="chapter-item expanded "><a href="../../zh/declaration-files/consumption.html"><strong aria-hidden="true">5.8.</strong> 使用</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">TypeScript for JavaScript</li><li class="chapter-item expanded "><a href="../../zh/javascript/type-checking-javascript-files.html"><strong aria-hidden="true">6.</strong> JavaScript 文件里的类型检查</a></li><li class="chapter-item expanded affix "><li class="part-title">工程配置</li><li class="chapter-item expanded "><a href="../../zh/project-config/index.html"><strong aria-hidden="true">7.</strong> 工程配置</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/project-config/tsconfig.json.html"><strong aria-hidden="true">7.1.</strong> tsconfig.json</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/project-references.html"><strong aria-hidden="true">7.2.</strong> 工程引用</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/typings-for-npm-packages.html"><strong aria-hidden="true">7.3.</strong> NPM 包的类型</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/compiler-options.html"><strong aria-hidden="true">7.4.</strong> 编译选项</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/configuring-watch.html"><strong aria-hidden="true">7.5.</strong> 配置 Watch</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/compiler-options-in-msbuild.html"><strong aria-hidden="true">7.6.</strong> 在 MSBuild 里使用编译选项</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/integrating-with-build-tools.html"><strong aria-hidden="true">7.7.</strong> 与其它构建工具整合</a></li><li class="chapter-item expanded "><a href="../../zh/project-config/nightly-builds.html"><strong aria-hidden="true">7.8.</strong> 使用 TypeScript 的每日构建版本</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">版本发布说明（Release Notes）</li><li class="chapter-item expanded "><a href="../../zh/release-notes/index.html"><strong aria-hidden="true">8.</strong> 新增功能</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.4.html"><strong aria-hidden="true">8.1.</strong> TypeScript 5.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.3.html"><strong aria-hidden="true">8.2.</strong> TypeScript 5.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.2.html"><strong aria-hidden="true">8.3.</strong> TypeScript 5.2</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.1.html"><strong aria-hidden="true">8.4.</strong> TypeScript 5.1</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-5.0.html"><strong aria-hidden="true">8.5.</strong> TypeScript 5.0</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.9.html"><strong aria-hidden="true">8.6.</strong> TypeScript 4.9</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.8.html"><strong aria-hidden="true">8.7.</strong> TypeScript 4.8</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.7.html"><strong aria-hidden="true">8.8.</strong> TypeScript 4.7</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.6.html"><strong aria-hidden="true">8.9.</strong> TypeScript 4.6</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.5.html"><strong aria-hidden="true">8.10.</strong> TypeScript 4.5</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.4.html"><strong aria-hidden="true">8.11.</strong> TypeScript 4.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.3.html"><strong aria-hidden="true">8.12.</strong> TypeScript 4.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.2.html"><strong aria-hidden="true">8.13.</strong> TypeScript 4.2</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.1.html"><strong aria-hidden="true">8.14.</strong> TypeScript 4.1</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-4.0.html"><strong aria-hidden="true">8.15.</strong> TypeScript 4.0</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.9.html"><strong aria-hidden="true">8.16.</strong> TypeScript 3.9</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.8.html"><strong aria-hidden="true">8.17.</strong> TypeScript 3.8</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.7.html"><strong aria-hidden="true">8.18.</strong> TypeScript 3.7</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.6.html"><strong aria-hidden="true">8.19.</strong> TypeScript 3.6</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.5.html"><strong aria-hidden="true">8.20.</strong> TypeScript 3.5</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.4.html"><strong aria-hidden="true">8.21.</strong> TypeScript 3.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.3.html"><strong aria-hidden="true">8.22.</strong> TypeScript 3.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.2.html"><strong aria-hidden="true">8.23.</strong> TypeScript 3.2</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.1.html"><strong aria-hidden="true">8.24.</strong> TypeScript 3.1</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-3.0.html"><strong aria-hidden="true">8.25.</strong> TypeScript 3.0</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.9.html"><strong aria-hidden="true">8.26.</strong> TypeScript 2.9</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.8.html"><strong aria-hidden="true">8.27.</strong> TypeScript 2.8</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.7.html"><strong aria-hidden="true">8.28.</strong> TypeScript 2.7</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.6.html"><strong aria-hidden="true">8.29.</strong> TypeScript 2.6</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.5.html"><strong aria-hidden="true">8.30.</strong> TypeScript 2.5</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.4.html"><strong aria-hidden="true">8.31.</strong> TypeScript 2.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.3.html"><strong aria-hidden="true">8.32.</strong> TypeScript 2.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.2.html"><strong aria-hidden="true">8.33.</strong> TypeScript 2.2</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.1.html"><strong aria-hidden="true">8.34.</strong> TypeScript 2.1</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-2.0.html"><strong aria-hidden="true">8.35.</strong> TypeScript 2.0</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.8.html"><strong aria-hidden="true">8.36.</strong> TypeScript 1.8</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.7.html"><strong aria-hidden="true">8.37.</strong> TypeScript 1.7</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.6.html"><strong aria-hidden="true">8.38.</strong> TypeScript 1.6</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.5.html"><strong aria-hidden="true">8.39.</strong> TypeScript 1.5</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.4.html"><strong aria-hidden="true">8.40.</strong> TypeScript 1.4</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.3.html"><strong aria-hidden="true">8.41.</strong> TypeScript 1.3</a></li><li class="chapter-item expanded "><a href="../../zh/release-notes/typescript-1.1.html"><strong aria-hidden="true">8.42.</strong> TypeScript 1.1</a></li></ol></li><li class="chapter-item expanded "><li class="part-title">破坏性改动（Breaking Changes）</li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/index.html"><strong aria-hidden="true">9.</strong> Breaking Changes</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.6.html"><strong aria-hidden="true">9.1.</strong> TypeScript 3.6</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.5.html"><strong aria-hidden="true">9.2.</strong> TypeScript 3.5</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.4.html"><strong aria-hidden="true">9.3.</strong> TypeScript 3.4</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.2.html"><strong aria-hidden="true">9.4.</strong> TypeScript 3.2</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.1.html"><strong aria-hidden="true">9.5.</strong> TypeScript 3.1</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-3.0.html"><strong aria-hidden="true">9.6.</strong> TypeScript 3.0</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.9.html"><strong aria-hidden="true">9.7.</strong> TypeScript 2.9</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.8.html"><strong aria-hidden="true">9.8.</strong> TypeScript 2.8</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.7.html"><strong aria-hidden="true">9.9.</strong> TypeScript 2.7</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.6.html"><strong aria-hidden="true">9.10.</strong> TypeScript 2.6</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.4.html"><strong aria-hidden="true">9.11.</strong> TypeScript 2.4</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.3.html"><strong aria-hidden="true">9.12.</strong> TypeScript 2.3</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.2.html"><strong aria-hidden="true">9.13.</strong> TypeScript 2.2</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.1.html"><strong aria-hidden="true">9.14.</strong> TypeScript 2.1</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-2.0.html"><strong aria-hidden="true">9.15.</strong> TypeScript 2.0</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.8.html"><strong aria-hidden="true">9.16.</strong> TypeScript 1.8</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.7.html"><strong aria-hidden="true">9.17.</strong> TypeScript 1.7</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.6.html"><strong aria-hidden="true">9.18.</strong> TypeScript 1.6</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.5.html"><strong aria-hidden="true">9.19.</strong> TypeScript 1.5</a></li><li class="chapter-item expanded "><a href="../../zh/breaking-changes/typescript-1.4.html"><strong aria-hidden="true">9.20.</strong> TypeScript 1.4</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle">
                <div class="sidebar-resize-indicator"></div>
            </div>
        </nav>

        <!-- Track and set sidebar scroll position -->
        <script>
            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
            sidebarScrollbox.addEventListener('click', function(e) {
                if (e.target.tagName === 'A') {
                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
                }
            }, { passive: true });
            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
            sessionStorage.removeItem('sidebar-scroll');
            if (sidebarScrollTop) {
                // preserve sidebar scroll position when navigating via links within sidebar
                sidebarScrollbox.scrollTop = sidebarScrollTop;
            } else {
                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
                var activeSection = document.querySelector('#sidebar .active');
                if (activeSection) {
                    activeSection.scrollIntoView({ block: 'center' });
                }
            }
        </script>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </label>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">TypeScript 使用指南手册</h1>

                    <div class="right-buttons">
                        <a href="../../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="变量声明"><a class="header" href="#变量声明">变量声明</a></h1>
<h2 id="变量声明-1"><a class="header" href="#变量声明-1">变量声明</a></h2>
<p><code>let</code>和<code>const</code>是JavaScript里相对较新的变量声明方式。 <a href="basic-types.html#a-note-about-let">像我们之前提到过的</a>，<code>let</code>在很多方面与<code>var</code>是相似的，但是可以帮助大家避免在JavaScript里常见一些问题。 <code>const</code>是对<code>let</code>的一个增强，它能阻止对一个变量再次赋值。</p>
<p>因为TypeScript是JavaScript的超集，所以它本身就支持<code>let</code>和<code>const</code>。 下面我们会详细说明这些新的声明方式以及为什么推荐使用它们来代替<code>var</code>。</p>
<p>如果你之前使用JavaScript时没有特别在意，那么这节内容会唤起你的回忆。 如果你已经对<code>var</code>声明的怪异之处了如指掌，那么你可以轻松地略过这节。</p>
<h2 id="var-声明"><a class="header" href="#var-声明"><code>var</code> 声明</a></h2>
<p>一直以来我们都是通过<code>var</code>关键字定义JavaScript变量。</p>
<pre><code class="language-typescript">var a = 10;
</code></pre>
<p>大家都能理解，这里定义了一个名为<code>a</code>值为<code>10</code>的变量。</p>
<p>我们也可以在函数内部定义变量：</p>
<pre><code class="language-typescript">function f() {
    var message = "Hello, world!";

    return message;
}
</code></pre>
<p>并且我们也可以在其它函数内部访问相同的变量。</p>
<pre><code class="language-typescript">function f() {
    var a = 10;
    return function g() {
        var b = a + 1;
        return b;
    }
}

var g = f();
g(); // returns 11;
</code></pre>
<p>上面的例子里，<code>g</code>可以获取到<code>f</code>函数里定义的<code>a</code>变量。 每当<code>g</code>被调用时，它都可以访问到<code>f</code>里的<code>a</code>变量。 即使当<code>g</code>在<code>f</code>已经执行完后才被调用，它仍然可以访问及修改<code>a</code>。</p>
<pre><code class="language-typescript">function f() {
    var a = 1;

    a = 2;
    var b = g();
    a = 3;

    return b;

    function g() {
        return a;
    }
}

f(); // returns 2
</code></pre>
<h3 id="作用域规则"><a class="header" href="#作用域规则">作用域规则</a></h3>
<p>对于熟悉其它语言的人来说，<code>var</code>声明有些奇怪的作用域规则。 看下面的例子：</p>
<pre><code class="language-typescript">function f(shouldInitialize: boolean) {
    if (shouldInitialize) {
        var x = 10;
    }

    return x;
}

f(true);  // returns '10'
f(false); // returns 'undefined'
</code></pre>
<p>有些读者可能要多看几遍这个例子。 变量<code>x</code>是定义在_<code>if</code>语句里面_，但是我们却可以在语句的外面访问它。 这是因为<code>var</code>声明可以在包含它的函数，模块，命名空间或全局作用域内部任何位置被访问（我们后面会详细介绍），包含它的代码块对此没有什么影响。 有些人称此为_<code>var</code>作用域_或_函数作用域_。 函数参数也使用函数作用域。</p>
<p>这些作用域规则可能会引发一些错误。 其中之一就是，多次声明同一个变量并不会报错：</p>
<pre><code class="language-typescript">function sumMatrix(matrix: number[][]) {
    var sum = 0;
    for (var i = 0; i &lt; matrix.length; i++) {
        var currentRow = matrix[i];
        for (var i = 0; i &lt; currentRow.length; i++) {
            sum += currentRow[i];
        }
    }

    return sum;
}
</code></pre>
<p>这里很容易看出一些问题，里层的<code>for</code>循环会覆盖变量<code>i</code>，因为所有<code>i</code>都引用相同的函数作用域内的变量。 有经验的开发者们很清楚，这些问题可能在代码审查时漏掉，引发无穷的麻烦。</p>
<h3 id="捕获变量怪异之处"><a class="header" href="#捕获变量怪异之处">捕获变量怪异之处</a></h3>
<p>快速的猜一下下面的代码会返回什么：</p>
<pre><code class="language-typescript">for (var i = 0; i &lt; 10; i++) {
    setTimeout(function() { console.log(i); }, 100 * i);
}
</code></pre>
<p>介绍一下，<code>setTimeout</code>会在若干毫秒的延时后执行一个函数（等待其它代码执行完毕）。</p>
<p>好吧，看一下结果：</p>
<pre><code class="language-text">10
10
10
10
10
10
10
10
10
10
</code></pre>
<p>很多JavaScript程序员对这种行为已经很熟悉了，但如果你很不解，你并不是一个人。 大多数人期望输出结果是这样：</p>
<pre><code class="language-text">0
1
2
3
4
5
6
7
8
9
</code></pre>
<p>还记得我们上面提到的捕获变量吗？ 我们传给<code>setTimeout</code>的每一个函数表达式实际上都引用了相同作用域里的同一个<code>i</code>。</p>
<p>让我们花点时间思考一下这是为什么。 <code>setTimeout</code>在若干毫秒后执行一个函数，并且是在<code>for</code>循环结束后。 <code>for</code>循环结束后，<code>i</code>的值为<code>10</code>。 所以当函数被调用的时候，它会打印出<code>10</code>！</p>
<p>一个通常的解决方法是使用立即执行的函数表达式（IIFE）来捕获每次迭代时<code>i</code>的值：</p>
<pre><code class="language-typescript">for (var i = 0; i &lt; 10; i++) {
    // capture the current state of 'i'
    // by invoking a function with its current value
    (function(i) {
        setTimeout(function() { console.log(i); }, 100 * i);
    })(i);
}
</code></pre>
<p>这种奇怪的形式我们已经司空见惯了。 参数<code>i</code>会覆盖<code>for</code>循环里的<code>i</code>，但是因为我们起了同样的名字，所以我们不用怎么改<code>for</code>循环体里的代码。</p>
<h2 id="let-声明"><a class="header" href="#let-声明"><code>let</code> 声明</a></h2>
<p>现在你已经知道了<code>var</code>存在一些问题，这恰好说明了为什么用<code>let</code>语句来声明变量。 除了名字不同外，<code>let</code>与<code>var</code>的写法一致。</p>
<pre><code class="language-typescript">let hello = "Hello!";
</code></pre>
<p>主要的区别不在语法上，而是语义，我们接下来会深入研究。</p>
<h3 id="块作用域"><a class="header" href="#块作用域">块作用域</a></h3>
<p>当用<code>let</code>声明一个变量，它使用的是_词法作用域_或_块作用域_。 不同于使用<code>var</code>声明的变量那样可以在包含它们的函数外访问，块作用域变量在包含它们的块或<code>for</code>循环之外是不能访问的。</p>
<pre><code class="language-typescript">function f(input: boolean) {
    let a = 100;

    if (input) {
        // Still okay to reference 'a'
        let b = a + 1;
        return b;
    }

    // Error: 'b' doesn't exist here
    return b;
}
</code></pre>
<p>这里我们定义了2个变量<code>a</code>和<code>b</code>。 <code>a</code>的作用域是<code>f</code>函数体内，而<code>b</code>的作用域是<code>if</code>语句块里。</p>
<p>在<code>catch</code>语句里声明的变量也具有同样的作用域规则。</p>
<pre><code class="language-typescript">try {
    throw "oh no!";
}
catch (e) {
    console.log("Oh well.");
}

// Error: 'e' doesn't exist here
console.log(e);
</code></pre>
<p>拥有块级作用域的变量的另一个特点是，它们不能在被声明之前读或写。 虽然这些变量始终“存在”于它们的作用域里，但在直到声明它的代码之前的区域都属于_暂时性死区_。 它只是用来说明我们不能在<code>let</code>语句之前访问它们，幸运的是TypeScript可以告诉我们这些信息。</p>
<pre><code class="language-typescript">a++; // illegal to use 'a' before it's declared;
let a;
</code></pre>
<p>注意一点，我们仍然可以在一个拥有块作用域变量被声明前_获取_它。 只是我们不能在变量声明前去调用那个函数。 如果生成代码目标为ES2015，现代的运行时会抛出一个错误；然而，现今TypeScript是不会报错的。</p>
<pre><code class="language-typescript">function foo() {
    // okay to capture 'a'
    return a;
}

// 不能在'a'被声明前调用'foo'
// 运行时应该抛出错误
foo();

let a;
</code></pre>
<p>关于_暂时性死区_的更多信息，查看这里<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone_and_errors_with_let">Mozilla Developer Network</a>.</p>
<h3 id="重声明及屏蔽"><a class="header" href="#重声明及屏蔽">重声明及屏蔽</a></h3>
<p>我们提过使用<code>var</code>声明时，它不在乎你声明多少次；你只会得到1个。</p>
<pre><code class="language-typescript">function f(x) {
    var x;
    var x;

    if (true) {
        var x;
    }
}
</code></pre>
<p>在上面的例子里，所有<code>x</code>的声明实际上都引用一个_相同_的<code>x</code>，并且这是完全有效的代码。 这经常会成为bug的来源。 好的是，<code>let</code>声明就不会这么宽松了。</p>
<pre><code class="language-typescript">let x = 10;
let x = 20; // 错误，不能在1个作用域里多次声明`x`
</code></pre>
<p>并不是要求两个均是块级作用域的声明TypeScript才会给出一个错误的警告。</p>
<pre><code class="language-typescript">function f(x) {
    let x = 100; // error: interferes with parameter declaration
}

function g() {
    let x = 100;
    var x = 100; // error: can't have both declarations of 'x'
}
</code></pre>
<p>并不是说块级作用域变量不能用函数作用域变量来声明。 而是块级作用域变量需要在明显不同的块里声明。</p>
<pre><code class="language-typescript">function f(condition, x) {
    if (condition) {
        let x = 100;
        return x;
    }

    return x;
}

f(false, 0); // returns 0
f(true, 0);  // returns 100
</code></pre>
<p>在一个嵌套作用域里引入一个新名字的行为称做_屏蔽_。 它是一把双刃剑，它可能会不小心地引入新问题，同时也可能会解决一些错误。 例如，假设我们现在用<code>let</code>重写之前的<code>sumMatrix</code>函数。</p>
<pre><code class="language-typescript">function sumMatrix(matrix: number[][]) {
    let sum = 0;
    for (let i = 0; i &lt; matrix.length; i++) {
        var currentRow = matrix[i];
        for (let i = 0; i &lt; currentRow.length; i++) {
            sum += currentRow[i];
        }
    }

    return sum;
}
</code></pre>
<p>这个版本的循环能得到正确的结果，因为内层循环的<code>i</code>可以屏蔽掉外层循环的<code>i</code>。</p>
<p>_通常_来讲应该避免使用屏蔽，因为我们需要写出清晰的代码。 同时也有些场景适合利用它，你需要好好打算一下。</p>
<h3 id="块级作用域变量的获取"><a class="header" href="#块级作用域变量的获取">块级作用域变量的获取</a></h3>
<p>在我们最初谈及获取用<code>var</code>声明的变量时，我们简略地探究了一下在获取到了变量之后它的行为是怎样的。 直观地讲，每次进入一个作用域时，它创建了一个变量的_环境_。 就算作用域内代码已经执行完毕，这个环境与其捕获的变量依然存在。</p>
<pre><code class="language-typescript">function theCityThatAlwaysSleeps() {
    let getCity;

    if (true) {
        let city = "Seattle";
        getCity = function() {
            return city;
        }
    }

    return getCity();
}
</code></pre>
<p>因为我们已经在<code>city</code>的环境里获取到了<code>city</code>，所以就算<code>if</code>语句执行结束后我们仍然可以访问它。</p>
<p>回想一下前面<code>setTimeout</code>的例子，我们最后需要使用立即执行的函数表达式来获取每次<code>for</code>循环迭代里的状态。 实际上，我们做的是为获取到的变量创建了一个新的变量环境。 这样做挺痛苦的，但是幸运的是，你不必在TypeScript里这样做了。</p>
<p>当<code>let</code>声明出现在循环体里时拥有完全不同的行为。 不仅是在循环里引入了一个新的变量环境，而是针对_每次迭代_都会创建这样一个新作用域。 这就是我们在使用立即执行的函数表达式时做的事，所以在<code>setTimeout</code>例子里我们仅使用<code>let</code>声明就可以了。</p>
<pre><code class="language-typescript">for (let i = 0; i &lt; 10 ; i++) {
    setTimeout(function() {console.log(i); }, 100 * i);
}
</code></pre>
<p>会输出与预料一致的结果：</p>
<pre><code class="language-text">0
1
2
3
4
5
6
7
8
9
</code></pre>
<h2 id="const-声明"><a class="header" href="#const-声明"><code>const</code> 声明</a></h2>
<p><code>const</code> 声明是声明变量的另一种方式。</p>
<pre><code class="language-typescript">const numLivesForCat = 9;
</code></pre>
<p>它们与<code>let</code>声明相似，但是就像它的名字所表达的，它们被赋值后不能再改变。 换句话说，它们拥有与<code>let</code>相同的作用域规则，但是不能对它们重新赋值。</p>
<p>这很好理解，它们引用的值是_不可变的_。</p>
<pre><code class="language-typescript">const numLivesForCat = 9;
const kitty = {
    name: "Aurora",
    numLives: numLivesForCat,
}

// Error
kitty = {
    name: "Danielle",
    numLives: numLivesForCat
};

// all "okay"
kitty.name = "Rory";
kitty.name = "Kitty";
kitty.name = "Cat";
kitty.numLives--;
</code></pre>
<p>除非你使用特殊的方法去避免，实际上<code>const</code>变量的内部状态是可修改的。 幸运的是，TypeScript允许你将对象的成员设置成只读的。 <a href="interfaces.html">接口</a>一章有详细说明。</p>
<h2 id="let-vs-const"><a class="header" href="#let-vs-const"><code>let</code> vs. <code>const</code></a></h2>
<p>现在我们有两种作用域相似的声明方式，我们自然会问到底应该使用哪个。 与大多数泛泛的问题一样，答案是：依情况而定。</p>
<p>使用<a href="https://en.wikipedia.org/wiki/Principle_of_least_privilege">最小特权原则</a>，所有变量除了你计划去修改的都应该使用<code>const</code>。 基本原则就是如果一个变量不需要对它写入，那么其它使用这些代码的人也不能够写入它们，并且要思考为什么会需要对这些变量重新赋值。 使用<code>const</code>也可以让我们更容易的推测数据的流动。</p>
<p>跟据你的自己判断，如果合适的话，与团队成员商议一下。</p>
<p>这个手册大部分地方都使用了<code>let</code>声明。</p>
<h2 id="解构"><a class="header" href="#解构">解构</a></h2>
<p>TypeScript 包含的另一个 ECMAScript 2015 特性就是解构。完整列表请参见 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">the article on the Mozilla Developer Network</a>。 本章，我们将给出一个简短的概述。</p>
<h3 id="解构数组"><a class="header" href="#解构数组">解构数组</a></h3>
<p>最简单的解构莫过于数组的解构赋值了：</p>
<pre><code class="language-typescript">let input = [1, 2];
let [first, second] = input;
console.log(first); // outputs 1
console.log(second); // outputs 2
</code></pre>
<p>这创建了2个命名变量 <code>first</code> 和 <code>second</code>。 相当于使用了索引，但更为方便：</p>
<pre><code class="language-typescript">first = input[0];
second = input[1];
</code></pre>
<p>解构也可以作用于已声明的变量：</p>
<pre><code class="language-typescript">// swap variables
[first, second] = [second, first];
</code></pre>
<p>类似地，也可以作用于函数参数：</p>
<pre><code class="language-typescript">function f([first, second]: [number, number]) {
    console.log(first);
    console.log(second);
}
f([1, 2]);
</code></pre>
<p>你可以在数组里使用<code>...</code>语法创建剩余变量：</p>
<pre><code class="language-typescript">let [first, ...rest] = [1, 2, 3, 4];
console.log(first); // outputs 1
console.log(rest); // outputs [ 2, 3, 4 ]
</code></pre>
<p>当然，由于是JavaScript, 你可以忽略你不关心的尾随元素：</p>
<pre><code class="language-typescript">let [first] = [1, 2, 3, 4];
console.log(first); // outputs 1
</code></pre>
<p>或其它元素：</p>
<pre><code class="language-typescript">let [, second, , fourth] = [1, 2, 3, 4];
console.log(second); // outputs 2
console.log(fourth); // outputs 4
</code></pre>
<h3 id="解构元组"><a class="header" href="#解构元组">解构元组</a></h3>
<p>元组可以像数组一样解构；解构后的变量获得对应元组元素的类型：</p>
<pre><code class="language-typescript">let tuple: [number, string, boolean] = [7, "hello", true];

let [a, b, c] = tuple; // a: number, b: string, c: boolean
</code></pre>
<p>当解构元组时，若超出元组索引范围将报错：</p>
<pre><code class="language-typescript">let [a, b, c, d] = tuple; // 错误，没有索引为3的元素
</code></pre>
<p>与数组一样，可以作用<code>...</code>来解构元组的剩余元素，从而得到一个短的元组：</p>
<pre><code class="language-typescript">let [a, ...bc] = tuple; // bc: [string, boolean]
let [a, b, c, ...d] = tuple; // d: [], the empty tuple
</code></pre>
<p>或者，忽略末尾元素或其它元素：</p>
<pre><code class="language-typescript">let [a] = tuple; // a: number
let [, b] = tuple; // b: string
</code></pre>
<h3 id="对象解构"><a class="header" href="#对象解构">对象解构</a></h3>
<p>你也可以解构对象：</p>
<pre><code class="language-typescript">let o = {
    a: "foo",
    b: 12,
    c: "bar"
};
let { a, b } = o;
</code></pre>
<p>这通过 <code>o.a</code> and <code>o.b</code> 创建了 <code>a</code> 和 <code>b</code> 。 注意，如果你不需要 <code>c</code> 你可以忽略它。</p>
<p>就像数组解构，你可以用没有声明的赋值：</p>
<pre><code class="language-typescript">({ a, b } = { a: "baz", b: 101 });
</code></pre>
<p>注意，我们需要用括号将它括起来，因为Javascript通常会将以 <code>{</code> 起始的语句解析为一个块。</p>
<p>你可以在对象里使用<code>...</code>语法创建剩余变量：</p>
<pre><code class="language-typescript">let { a, ...passthrough } = o;
let total = passthrough.b + passthrough.c.length;
</code></pre>
<h4 id="属性重命名"><a class="header" href="#属性重命名">属性重命名</a></h4>
<p>你也可以给属性以不同的名字：</p>
<pre><code class="language-typescript">let { a: newName1, b: newName2 } = o;
</code></pre>
<p>这里的语法开始变得混乱。 你可以将 <code>a: newName1</code> 读做 "<code>a</code> 作为 <code>newName1</code>"。 方向是从左到右，好像你写成了以下样子：</p>
<pre><code class="language-typescript">let newName1 = o.a;
let newName2 = o.b;
</code></pre>
<p>令人困惑的是，这里的冒号_不是_指示类型的。 如果你想指定它的类型， 仍然需要在其后写上完整的模式。</p>
<pre><code class="language-typescript">let {a, b}: {a: string, b: number} = o;
</code></pre>
<h4 id="默认值"><a class="header" href="#默认值">默认值</a></h4>
<p>我们可以为属性指定一个默认值，当属性值为<code>undefined</code>时，将使用该默认值：</p>
<pre><code class="language-typescript">function keepWholeObject(wholeObject: { a: string, b?: number }) {
    let { a, b = 1001 } = wholeObject;
}
</code></pre>
<p>此例中，<code>b?</code>表明<code>b</code>是可选的，因此它可能为<code>undefined</code>。 现在，即使 <code>b</code> 为 undefined ， <code>keepWholeObject</code> 函数的变量 <code>wholeObject</code> 的属性 <code>a</code> 和 <code>b</code> 都会有值。</p>
<h3 id="函数声明"><a class="header" href="#函数声明">函数声明</a></h3>
<p>解构也能用于函数声明。 看以下简单的情况：</p>
<pre><code class="language-typescript">type C = { a: string, b?: number }
function f({ a, b }: C): void {
    // ...
}
</code></pre>
<p>但是，通常情况下更多的是指定默认值，解构默认值有些棘手。 首先，你需要在默认值之前设置其格式。</p>
<pre><code class="language-typescript">function f({ a="", b=0 } = {}): void {
    // ...
}
f();
</code></pre>
<blockquote>
<p>上面的代码是一个类型推断的例子，将在本手册后文介绍。</p>
</blockquote>
<p>其次，你需要知道在解构属性上给予一个默认或可选的属性用来替换主初始化列表。 要知道 <code>C</code> 的定义有一个 <code>b</code> 可选属性：</p>
<pre><code class="language-typescript">function f({ a, b = 0 } = { a: "" }): void {
    // ...
}
f({ a: "yes" }); // ok, default b = 0
f(); // ok, default to {a: ""}, which then defaults b = 0
f({}); // error, 'a' is required if you supply an argument
</code></pre>
<p>要小心使用解构。 从前面的例子可以看出，就算是最简单的解构表达式也是难以理解的。 尤其当存在深层嵌套解构的时候，就算这时没有堆叠在一起的重命名，默认值和类型注解，也是令人难以理解的。 解构表达式要尽量保持小而简单。 你自己也可以直接使用解构将会生成的赋值表达式。</p>
<h3 id="展开"><a class="header" href="#展开">展开</a></h3>
<p>展开操作符正与解构相反。 它允许你将一个数组展开为另一个数组，或将一个对象展开为另一个对象。 例如：</p>
<pre><code class="language-typescript">let first = [1, 2];
let second = [3, 4];
let bothPlus = [0, ...first, ...second, 5];
</code></pre>
<p>这会令<code>bothPlus</code>的值为<code>[0, 1, 2, 3, 4, 5]</code>。 展开操作创建了<code>first</code>和<code>second</code>的一份浅拷贝。 它们不会被展开操作所改变。</p>
<p>你还可以展开对象：</p>
<pre><code class="language-typescript">let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { ...defaults, food: "rich" };
</code></pre>
<p><code>search</code>的值为<code>{ food: "rich", price: "$$", ambiance: "noisy" }</code>。 对象的展开比数组的展开要复杂的多。 像数组展开一样，它是从左至右进行处理，但结果仍为对象。 这就意味着出现在展开对象后面的属性会覆盖前面的属性。 因此，如果我们修改上面的例子，在结尾处进行展开的话：</p>
<pre><code class="language-typescript">let defaults = { food: "spicy", price: "$$", ambiance: "noisy" };
let search = { food: "rich", ...defaults };
</code></pre>
<p>那么，<code>defaults</code>里的<code>food</code>属性会重写<code>food: "rich"</code>，在这里这并不是我们想要的结果。</p>
<p>对象展开还有其它一些意想不到的限制。 首先，它仅包含对象 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties">自身的可枚举属性</a>。 大体上是说当你展开一个对象实例时，你会丢失其方法：</p>
<pre><code class="language-typescript">class C {
  p = 12;
  m() {
  }
}
let c = new C();
let clone = { ...c };
clone.p; // ok
clone.m(); // error!
</code></pre>
<p>其次，TypeScript编译器不允许展开泛型函数上的类型参数。 这个特性会在TypeScript的未来版本中考虑实现。</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="../../zh/reference/type-inference.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next prefetch" href="../../zh/handbook-v2/index.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="../../zh/reference/type-inference.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next prefetch" href="../../zh/handbook-v2/index.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>




        <script>
            window.playground_copyable = true;
        </script>


        <script src="../../elasticlunr.min.js"></script>
        <script src="../../mark.min.js"></script>
        <script src="../../searcher.js"></script>

        <script src="../../clipboard.min.js"></script>
        <script src="../../highlight.js"></script>
        <script src="../../book.js"></script>

        <!-- Custom JS scripts -->


    </div>
    </body>
</html>
